; (function ($) {
    $.tankBattles = $.tankBattles || {};

    // Game objects
    var drawEngine,
	dataContext,
    timerId,
	keysDown = {},
    then,

	// Entities
	DrawEngine = function (ctx) {
	    this.ctx = ctx;
	    this.render = function (img, sx, sy, swidth, sheight, x, y, width, height) {
	        /// <summary>Clip the image, position the clipped part and render</summary>
	        /// <param name="img" type="Image">Specifies the image element to use.</param>
	        /// <param name="sx" type="Number">Optional. The x coordinate where to start clipping.</param>
	        /// <param name="sy" type="Number">Optional. The y coordinate where to start clipping.</param>
	        /// <param name="swidth" type="Number">Optional. The width of the clipped image.</param>
	        /// <param name="sheight" type="Number">Optional. The height of the clipped image.</param>
	        /// <param name="x" type="Number">The x coordinate where to place the image on the canvas.</param>
	        /// <param name="y" type="Number">The y coordinate where to place the image on the canvas.</param>
	        /// <param name="width" type="Number">Optional. The width of the image to use (stretch or reduce the image).</param>
	        /// <param name="height" type="Number">Optional. The height of the image to use (stretch or reduce the image).</param>
	        sx = sx || 0;
	        sy = sy || 0;
	        width = width || img.width;
	        height = height || img.height;
	        swidth = swidth || width;
	        sheight = sheight || height;
	        this.ctx.drawImage(img, sx, sy, swidth, sheight, x, y, width, height);
	    }
	},

	// Events
	attachHandlers = function (gameElement) {
	    gameElement.addEventListener("keydown", function (e) {
	        e.preventDefault();
	        e.stopPropagation();
	        keysDown[e.keyCode] = true;
	    }, false);
	    gameElement.addEventListener("keyup", function (e) {
	        e.preventDefault();
	        e.stopPropagation();
	        delete keysDown[e.keyCode];
	    }, false);
	},

	// The main game loop
	main = function () {
	    var ctx = dataContext,
            now = Date.now(),
            delta = now - then,
            dt = delta / 1000;

	    if (ctx.beforeRenderEvent) {
	        ctx.beforeRenderEvent(dt, keysDown);
	    }

	    if (ctx.gameObjs) {
	        for (var i = 0, len = ctx.gameObjs.length; i < len; i++) {
	            ctx.gameObjs[i].render(drawEngine, dt);
	        }
	    }

	    if (ctx.afterRenderEvent) {
	        ctx.afterRenderEvent(dt, keysDown);
	    }
	    then = now;
	};

    $.tankBattles.core = {
        register: function (wrapperId, width, height, options) {
            // CREATE CANVAS
            var w = document.getElementById(wrapperId),
                canvas = document.createElement("canvas");
            canvas.width = width;
            canvas.height = height;
            w.appendChild(canvas);

            // INIT DRAW ENGINE
            drawEngine = new DrawEngine(canvas.getContext("2d"));

            // REGISTER CONTEXT
            dataContext = options;
            attachHandlers(window);

            options.startGame = function () {
                then = Date.now();

                // Execute as fast as possible
                timerId = setInterval(main, 1);
            };

            options.stopGame = function () {
                clearInterval(timerId);
            };
        }
    }
})(epam = typeof epam !== "undefined" ? epam : {});
